package tk.sunlatus.tools.code;

/** 
 * @author Jason 
 * @version 1.0 
 * 给出的一个java源文件或者目录, 统计出该java源文件或目录下所有的java源文件中 包含的空白行,注释行以及代码行. 
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

public class CodeCounter {
    // 代码行
    private long CodeLine = 0;
    // 注释行
    private long CommentLine = 0;
    // 空白行
    private long BlankLine = 0;
    // 统计文件个数
    private int Files = 0;

    StringBuffer countResult = new StringBuffer(512);

    private void doCountTask(File file) throws Exception {
        if (null == file) {
            // 文件为空,返回
            return;
        }
        if (file.isFile() && file.getName().matches(".*\\.java$")) {
            // 对java源文件进行行数统计
            Files++;
            fileCount(file);
        } else if (file.isDirectory()) {
            File[] files = file.listFiles(new FileFilter() {

                public boolean accept(File file) {
                    return (file.isDirectory() && !file.getAbsolutePath().contains("tools.secret"))
                        || (file.getName().matches(".*\\.java$") && !file.getName().matches(".*?CodeCounter\\.java$"));
                }
            });
            for (File f : files) {
                // 递归调用,直到每个子文件下的java源文件都被统计
                doCountTask(f);
            }
        }
    }

    private void fileCount(File file) {
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line = "";
            while ((line = br.readLine()) != null) {
                if (line.matches("(\\s*/\\*.*)|(\\s*\\*.*)|(\\s*//.*)")) {
                    // 除去空白的字符(如制表符),以"/*","*","//"开头的算作注释行
                    this.CommentLine++;
                } else if (line.matches("\\s*")) {
                    // 由空白字符组成的算作空白行
                    this.BlankLine++;
                    // } else{
                } else if (line.matches(".*?[{};]$") && !line.matches("^import.*?;$")) {
                    // 除上面的两种外,算作代码行.包括java代码,注解等等...
                    this.CodeLine++;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void printfResult() {
        if (this.Files == 0) {
            countResult.append("未统计任何文件!");
            // LOGGER.debug(countResult);
            return;
        }
        countResult.append("一共统计了 ").append(Files).append(" 个java源文件.\n");

        double total = this.BlankLine + this.CodeLine + this.CommentLine;
        Double code = new Double(this.CodeLine / total);
        Double comment = new Double(this.CommentLine / total);
        Double blank = new Double(this.BlankLine / total);

        DecimalFormat format = new DecimalFormat();
        // 比例使用百分数表示
        format.setMultiplier(100);
        countResult.append("代码行:").append(CodeLine).append(" [").append(format.format(code)).append("%]\n");
        countResult.append("注释行:").append(CommentLine).append(" [").append(format.format(comment)).append("%]\n");
        countResult.append("空白行:").append(BlankLine).append(" [").append(format.format(blank)).append("%]\n");
        // LOGGER.debug(countResult);
    }

    // 提供给用户调用的方法
    public void doCount(File f) {
        try {
            this.doCountTask(f);
            this.printfResult();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 测试...
        CodeCounter cc = new CodeCounter();
        File f = new File("E:/10.eclipse_workspace/sunlatus");
        File result = new File("E:/10.eclipse_workspace/sunlatus/codeCountResult.txt");
        cc.doCount(f);
        FileWriter writer = null;
        try {
            if (!result.exists()) {
                result.createNewFile();
            }
            writer = new FileWriter(result, true);
            StringBuffer data = new StringBuffer(100);
            long time = System.currentTimeMillis();
            data.append("sunlotus:").append(time).append("(")
                .append(new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(time)).append(")").append("|")
                .append(cc.CodeLine).append("|").append(cc.CommentLine).append("|").append(cc.BlankLine).append("\n");
            writer.write(data.toString());
            writer.write(cc.countResult.toString());
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}